import linecache
import math
import numpy
from scipy import spatial
import os

class Proximity(object):
    
    
    PATH1 = os.path.dirname(__file__) + "/Input/"
#    PATH1 = ''
    PATH2 = os.path.dirname(__file__) + "/ProximityMatrix/"
#    PATH2 = 'ProximityMatrix/'

    def __init__(self, filename):
        self.name = filename
        self.input = Proximity.PATH1 + self.name
        def GetNumberofLines():
            lines = 0
            for line in open(self.input):
                lines += 1
            return lines
        def GetNumberofColumns():
            line = linecache.getline(self.input, 1)
            return len(line.split())
        
        self.output = ''
        self.lines = GetNumberofLines()
    #     for sample-docs
        self.columns = GetNumberofColumns() - 1
  #      self.columns = GetNumberofColumns()
        
        self.ProximityMatrix = numpy.zeros((self.lines, self.lines))
        
    def GetVector(self, number):
        # Get vector from line #number from file input
        # number starts from 1
        line = linecache.getline(self.input, number)
     #    for sample-docs
        return map(float, line.split()[1:])
   #     return map(float, line.split())
    
    def CalculateDistance(self, type):
        self.ClearOutput(type)
        ImagesVectors  = numpy.zeros((self.lines, self.columns))
        print 'Start reading file'
        for i in range(1,self.lines+1):
            ImagesVectors[i :] = self.GetVector(i)
        print 'Start calculating distances'
        for i in range(self.lines):
            print 'Calculating distance = ', i
            strdistance = ''
            vector1 = ImagesVectors[i,:]
            distances = []
            for j in range(self.lines):
                vector2 = ImagesVectors[j,:]
                distance = self.Distance(type, vector1, vector2)  
                distances.append(distance)
            self.ProximityMatrix[i,:] = distances
                #strdistance = strdistance + str(distance) + ' '
            #strdistance = strdistance + '\n'
            #f=open(self.output,  'a')
            #f.writelines(strdistance)
            #f.close()
        numpy.savetxt(self.output, self.ProximityMatrix)
            
    def ClearFile(self, filename):
        f=open(filename,  'w')
        f.writelines('')
        f.close()
        
    def ClearOutput(self, type):
        if type == 'Euclidean':
            self.output = Proximity.PATH2 + self.name +'_Euclidean.dist'
        elif type == 'Manhattan':
            self.output = Proximity.PATH2 + self.name +'_Manhattan.dist'     
        elif type == 'Maximum':
            self.output = Proximity.PATH2 + self.name +'_Maximum.dist'
        elif type == 'Mahalanoibis':
            self.output = Proximity.PATH2 + self.name + '_Mahalanoibis.dist'        
        elif type == 'Cosine':
            self.output = Proximity.PATH2 + self.name +'_Cosine.dist'  
        elif type == 'LinRel':
            self.output = Proximity.PATH2 + self.name +'_LinRel.dist'
        self.ClearFile(self.output)
        
    def Distance(self, type, vector1, vector2):
        if type == 'Euclidean':
            distance = math.sqrt(sum((vector1 - vector2)**2))
        elif type == 'Manhattan':
            distance = sum(abs(vector1-vector2))
        elif type == 'Maximum':
            distance = max(vector1-vector2) 
        elif type == 'Mahalanoibis':
            matrix = numpy.vstack((vector1,vector2)).T
            covariance = numpy.cov(matrix)
            distance = math.sqrt(numpy.dot(numpy.dot((vector1-vector2),numpy.linalg.pinv(covariance)),(vector1-vector2).T))
        elif type == 'Cosine':
            distance = 1-numpy.dot(vector1, vector2)/(math.sqrt(sum((vector1)**2))*math.sqrt(sum((vector2)**2)))
        elif type == 'LinRel':
            distance = numpy.sqrt(sum((numpy.exp(vector1)-numpy.exp(vector2))**2))
        return distance
    
#p = Proximity('features_lewis5000')
#p.CalculateDistance('Euclidean')

p = Proximity('sample-docs1000')
p.CalculateDistance('LinRel')
        